<script lang="ts" setup>
import { reactive, ref, nextTick } from "vue";
import * as xlsx from "xlsx";
import va from "@/rules/index";
import type {
  FormInstance,
  FormRules,
  UploadInstance,
  UploadProps,
  UploadRawFile,
  ElScrollbar,
} from "element-plus";

const emits = defineEmits(["refreshDataList"]);
const props = defineProps({
  fields: {
    type: Array,
    default: () => {
      return [];
    },
  },
  downTmp: {
    type: String,
    default: "",
  },
});
const uploadRef = ref<UploadInstance>();
const formRef = ref<FormInstance>();
const innerRef = ref<HTMLDivElement>();
const scrollbarRef = ref<InstanceType<typeof ElScrollbar>>();

const stepActive = ref(0);

const formData = ref<{
  fields: {
    excelFieldName: string;
    databaseFieldName: string;
    rulesType: string;
    rulesValue: string;
    errorAction?: 1 | 0;
    dataCheck?: 1 | 0;
    databaseFieldRequired?: boolean;
  }[];
  [key: string]: any;
}>({
  fileList: [],
  fields: [],
  excelData: [],
  errorAction: 1,
  dataCheck: 1,
});

//引入自定义验证规则
const formRules = reactive<FormRules>({
  fileList: [va.required()],
});
// reactive 数据双向绑定
const saveLoading: any = ref(false);
const formDialog: any = reactive<{
  top: string;
  width: string;
  type: string;
  title: string;
  span: number;
  visible: boolean;
}>({
  top: "10vh",
  width: "960px",
  type: "import",
  title: "导入",
  span: 12,
  visible: false,
});

const excelFields = ref<string[]>([]);
const excelDatas = ref<any[]>([]);

const rulesOptions = ref([
  {
    label: "无",
    value: "none",
  },
  {
    label: "数值",
    value: "age",
  },
  {
    label: "日期",
    value: "date",
  },
  {
    label: "手机号",
    value: "phone",
  },
  {
    label: "邮箱号码",
    value: "email",
  },
  {
    label: "正则表达式",
    value: "rex",
  },
]);

props.fields.forEach((element: any) => {
  if (element.import && element.import.required) {
    formData.value.fields.push({
      excelFieldName: "",
      databaseFieldName: element.prop,
      rulesType: "none",
      rulesValue: "",
      databaseFieldRequired: true,
    });
  }
});

const show = async (type: any, _data: any = {}) => {
  formDialog.type = type;
  if (type == "import") {
    // formData.value = {
    //   ...data,
    // };
    formDialog.title = "导入";
    formDialog.visible = true;
  }
};

/**
 * 把文件按照二进制进行读取
 * @param file
 * @returns
 */
const readFile = (file: File) => {
  return new Promise((resolve) => {
    let reader = new FileReader();
    reader.readAsBinaryString(file);
    reader.onload = (ev) => {
      resolve(ev.target?.result);
    };
  });
};

/**
 * 根据sheet索引读取Excel文件中的数据
 /**@param file 文件
 /** @param sheetIndex excel文件中sheet表索引 默认是从0开始
 /**@returns  将表中的数据以json形式的数据返回
 */
const readExcelFile = async (file: File, sheetIndex: number) => {
  try {
    let data: any = await readFile(file);
    let workbook = xlsx.read(data, { type: "binary" });
    let worksheet = workbook.Sheets[workbook.SheetNames[sheetIndex]];
    data = xlsx.utils.sheet_to_json(worksheet);

    excelFields.value = Object.keys(data[0]);
    excelDatas.value = data;
    return data;
  } catch (error) {
    saveLoading.value = false;
    console.log(error);
  }
  return false;
};

const before = (file: any) => {
  try {
    readExcelFile(file, 0);
  } catch (error) {
    saveLoading.value = false;
    console.log(error);
  }
  return false;
};

const handleExceed: UploadProps["onExceed"] = (files: any) => {
  uploadRef.value!.clearFiles();
  const file = files[0] as UploadRawFile;
  // file.uid = genFileId();
  uploadRef.value!.handleStart(file);
};

const handleChange: UploadProps["onChange"] = (uploadFile: any) => {
  formData.value.fields = formData.value.fields.map((item: any) => {
    item.rulesType = undefined;
    item.excelFieldName = undefined;
    return item;
  });
  before(uploadFile?.raw);
};

// 获取系统字段下拉选
const getDatabaseFields = (row: { databaseFieldRequired?: boolean }) => {
  if (row.databaseFieldRequired) {
    return props.fields.filter((item: any) => item.import && item.import.required);
  } else {
    const checkFieldNames = formData.value.fields.map(
      (item: { databaseFieldName: any; }) => item.databaseFieldName,
    );
    return props.fields
      .filter((item: any) => !(item.import && item.import.required))
      .map((item: any) => {
        item.disabled = checkFieldNames.includes(item.prop);
        return item;
      });
  }
};

const addSearchFilterItem = () => {
  if (!formData.value.fields) {
    formData.value.fields = [];
  }
  formData.value.fields.push({
    excelFieldName: "",
    databaseFieldName: getDatabaseFields({}).find((item: any) => !item.disabled)
      ?.prop,
    rulesType: "none",
    rulesValue: "",
    databaseFieldRequired: false,
  });
  // 使用
  nextTick(() => {
    scrollbarRef.value!.setScrollTop(innerRef.value!.clientHeight);
  });
};

const removeSearchFilterItem = (index: number) => {
  formData.value.fields.splice(index, 1);
};

const nextStep = async () => {
  const formEl = formRef.value;
  if (!formEl) return;
  saveLoading.value = true;

  await formEl.validate((valid: any, fields: any) => {
    console.log(formData.value);
    if (valid) {
      switch (stepActive.value) {
        // 第一步
        case 0:
          // uploadRef.value!.submit()
          break;

        default:
          break;
      }
      stepActive.value = stepActive.value + 1;
      saveLoading.value = false;
    } else {
      console.log("error submit!", fields);
      saveLoading.value = false;
      switch (stepActive.value) {
        // 第一步
        case 0:
          // uploadRef.value!.submit()
          break;
        case 1:
          ElMessage({
            message: `必填字段的映射关系必填`,
            type: "warning",
            grouping: true,
          });
          break;

        default:
          break;
      }
    }
  });
};

const successClose = () => {
  formDialog.visible = false;
}

defineExpose({ show });
</script>

<template>
  <el-button type="primary" plain icon="Upload" @click="show('import', {})">导入</el-button>

  <el-dialog :title="formDialog.title" v-model="formDialog.visible" :top="formDialog.top" :width="formDialog.width"
    :close-on-click-modal="false" :append-to-body="true">
    <el-steps :active="stepActive" finish-status="success" simple>
      <el-step title="选择文件" />
      <el-step title="字段映射" />
      <el-step title="导入配置" />
      <el-step title="数据概况" />
      <el-step title="导入结果" />
    </el-steps>
    <div class="mt-4">
      <el-form :model="formData" :rules="formRules" ref="formRef" label-width="90px" label-suffix=":"
        label-position="top">
        <el-row :gutter="20">
          <!-- 第一步上传文件 -->
          <el-col :span="24" v-if="stepActive === 0">
            <el-form-item label="上传文件" prop="fileList">
              <el-upload ref="uploadRef" v-model:file-list="formData.fileList" class="w-full" accept=".xls, .xlsx" drag
                action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" :multiple="false" :limit="1"
                :auto-upload="false" :on-change="handleChange" :on-exceed="handleExceed">
                <el-icon class="el-icon--upload">
                  <upload-filled />
                </el-icon>
                <div class="el-upload__text">
                  将文件拖到此处，或 <em>点击上传</em>
                </div>
                <template #tip>
                  <div class="el-upload__tip">
                    <span class="mr-2">仅允许导入xls、xlsx格式文件。</span>
                    <el-link :underline="false" type="primary" :href="downTmp" target="_blank">下载模板</el-link>
                  </div>
                </template>
              </el-upload>
            </el-form-item>
          </el-col>
          <!-- 第二部建立映射关系 -->
          <el-col :span="24" v-if="stepActive === 1">
            <el-card shadow="never" :body-style="{ padding: '0px' }">
              <div class="flex p-2">
                <div class="w-8 text-center mr-2">序号</div>
                <div class="flex-1">
                  <el-row :gutter="20">
                    <el-col :span="8">
                      <div class="text-center">数据库字段</div>
                    </el-col>
                    <el-col :span="8">
                      <div class="text-center">excel字段</div>
                    </el-col>
                    <el-col :span="8">
                      <div class="text-center">数据校验</div>
                    </el-col>
                  </el-row>
                </div>
                <div class="w-8 text-center ml-2">操作</div>
              </div>
            </el-card>
            <el-card shadow="never" :body-style="{ padding: '0px' }" class="mt-2">
              <el-scrollbar ref="scrollbarRef" :height="formData?.fields?.length > 5 ? '220px' : 'auto'" always>
                <div class="px-2 py-4" ref="innerRef">
                  <div v-for="(i, index) in formData.fields" class="flex"
                    :class="{ 'pb-2': index < formData?.fields?.length - 1 }" :key="index">
                    <div class="w-8 text-center mr-2" style="line-height: 32px">
                      {{ index + 1 }}
                    </div>
                    <div class="flex-1">
                      <el-row :gutter="20">
                        <el-col :span="8">
                          <el-form-item :prop="['fields', index, 'databaseFieldName']" style="margin: 0">
                            <el-tooltip effect="dark" content="必填字段" placement="top"
                              :disabled="!i.databaseFieldRequired">
                              <el-select v-model="i['databaseFieldName']" placeholder="选择" class="w-full"
                                :disabled="i.databaseFieldRequired" clearable>
                                <el-option v-for="item in getDatabaseFields(i)" :key="item.value" :label="item.label"
                                  :value="item.prop" :disabled="item.disabled">
                                  <span class="float-left mr-2">{{
                                    item.label
                                  }}</span>
                                  <span class="float-right text-gray-400">{{
                                    item.prop
                                  }}</span>
                                </el-option>
                              </el-select>
                            </el-tooltip>
                          </el-form-item>
                        </el-col>
                        <el-col :span="8">
                          <el-form-item :prop="['fields', index, 'excelFieldName']" style="margin: 0"
                            :required="i.databaseFieldRequired" inline-message :show-message="false">
                            <el-select v-model="i['excelFieldName']" placeholder="映射关系" class="w-full">
                              <el-option v-for="item in excelFields" :key="item" :label="item" :value="item" />
                            </el-select>
                          </el-form-item>
                        </el-col>
                        <el-col :span="8">
                          <el-form-item :prop="['fields', index, 'rulesType']" style="margin: 0">
                            <el-select v-model="i['rulesType']" placeholder="选择" class="w-full"
                              v-if="i['rulesType'] !== 'rex'">
                              <el-option v-for="item in rulesOptions" :key="item.value" :label="item.label"
                                :value="item.value">
                                <span class="float-left mr-2">{{
                                  item.label
                                }}</span>
                                <span class="float-right text-gray-400">{{
                                  item.value
                                }}</span>
                              </el-option>
                            </el-select>

                            <el-input v-model="i['rulesValue']" placeholder="输入" v-else>
                              <template #prepend>
                                <el-select v-model="i['rulesType']" placeholder="选择" style="width: 85px">
                                  <el-option v-for="item in rulesOptions" :key="item.value" :label="item.label"
                                    :value="item.value">
                                    <span class="float-left mr-2">{{
                                      item.label
                                    }}</span>
                                    <span class="float-right text-gray-400">{{
                                      item.value
                                    }}</span>
                                  </el-option>
                                </el-select>
                              </template>
                            </el-input>
                          </el-form-item>
                        </el-col>
                      </el-row>
                    </div>
                    <div class="w-8 text-center ml-2">
                      <el-tooltip v-if="!i.databaseFieldRequired" effect="dark" content="移除" placement="top">
                        <el-button text icon="Close" circle @click="removeSearchFilterItem(index)" />
                      </el-tooltip>
                      <el-tooltip v-else effect="dark" content="必填字段不可移除" placement="top">
                        <!-- <el-button link><span>*</span></el-button> -->
                        <el-button text icon="InfoFilled" circle />
                      </el-tooltip>
                    </div>
                  </div>
                  <el-empty description="请点击下方添加按钮增加映射关系" v-if="formData?.fields?.length === 0" />
                </div>
              </el-scrollbar>
            </el-card>
          </el-col>
          <!-- 第三步导入配置 -->
          <el-col :span="24" v-if="stepActive === 2">
            <el-card shadow="never" :body-style="{ padding: '20px' }">
              <el-row :gutter="20">
                <el-col :span="24">
                  <el-form-item label="执行数据校验" prop="dataCheck" required>
                    <el-radio-group v-model="formData.dataCheck">
                      <el-radio :value="1">是</el-radio>
                      <el-radio :value="0">否</el-radio>
                    </el-radio-group>
                  </el-form-item>
                </el-col>
                <el-col :span="24">
                  <el-form-item label="遇到错误" prop="errorAction" required>
                    <el-radio-group v-model="formData.errorAction">
                      <el-radio :value="1">继续</el-radio>
                      <el-radio :value="0">停止</el-radio>
                    </el-radio-group>
                  </el-form-item>
                </el-col>
              </el-row>
            </el-card>
          </el-col>
          <!-- 第四步信息 -->
          <el-col :span="24" v-if="stepActive === 3">
            <el-card shadow="never" :body-style="{ padding: '20px' }">
              <el-descriptions title="数据概况">
                <el-descriptions-item label="总数据量">{{ excelDatas.length }}
                </el-descriptions-item>
                <el-descriptions-item label="检验通过量">{{ excelDatas.length }}
                </el-descriptions-item>
                <el-descriptions-item label="检验失败量">{{ excelDatas.length }}
                </el-descriptions-item>
              </el-descriptions>
            </el-card>
          </el-col>
          <!-- 第五步结果 -->
          <el-col :span="24" v-if="stepActive === 4">
            <el-card shadow="never" :body-style="{ padding: '20px' }">
              <el-result icon="success" title="导入成功" sub-title="Please follow the instructions">
                <template #extra>
                  <el-button type="primary" @click="successClose()">关闭</el-button>
                </template>
              </el-result>
            </el-card>
          </el-col>
        </el-row>
      </el-form>
    </div>
    <template #footer>
      <span class="dialog-footer-left float-left" v-if="stepActive === 1">
        <el-tooltip effect="dark" content="超出" placement="top"
          :disabled="formData?.fields?.length < props.fields.length">
          <el-button icon="CirclePlus" @click="addSearchFilterItem"
            :disabled="formData?.fields?.length >= props.fields.length">添加</el-button>
        </el-tooltip>
      </span>
      <span class="dialog-footer">
        <el-button v-if="stepActive > 0 && stepActive < 4" type="primary" @click="stepActive = 0"><el-icon
            class="el-icon--left">
            <DArrowLeft />
          </el-icon>上一步</el-button>
        <el-button v-if="stepActive < 3" type="primary" @click="nextStep()" :loading="saveLoading">下一步<el-icon
            class="el-icon--right">
            <DArrowRight />
          </el-icon></el-button>
        <el-button v-if="stepActive === 3" type="primary" @click="nextStep()" icon="CircleCheck" :loading="saveLoading"
          auto-insert-space>导入</el-button>
        <!-- <el-button @click="formDialog.visible = false" icon="CircleClose">取 消</el-button> -->
      </span>
    </template>
  </el-dialog>
</template>
